/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package co.com.losalpes.marketplace.pirfb.beans;

import co.com.losalpes.marketplace.pirfb.bos.IntencionBO;
import co.com.losalpes.marketplace.pirfb.bos.SolicitudBO;
import co.com.losalpes.marketplace.pirfb.entities.Intencion;
import co.com.losalpes.marketplace.pirfb.entities.Solicitud;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import javax.ejb.Stateless;
import javax.persistence.EntityManager;
import javax.persistence.PersistenceContext;
import javax.persistence.Query;

/**
 *
 * @author Juan
 */
@Stateless
public class RFBBeanTest implements RFBBeanLocal {

    @PersistenceContext
    private EntityManager em;

    /**
     * Este metodo pemrite la creacion de las Intenciones tanto de compra como de venta dentro del MarketPLace de los Alpes
     * @param intencion
     * @return 
     */
    public String crearIntencion(IntencionBO intencion) {

        String numero = "INT" + System.currentTimeMillis();
        intencion.setNumero(numero);
        Intencion intencionEnt = new Intencion(intencion);
        em.persist(intencionEnt);
        return numero;
    }

    /**
     * - Recibe una intencion de compra o de venta busca el match si lo
     * encuentra crea la solicitud y cambia los estados de las intenciones si no
     * devuelve un null
     *
     * - Se debe verificar que ninguna de las intenciones se encuetre en estado
     * RECHAZADA en la tabla de solicitudes
     *
     * @param intencionBO
     * @return
     */
    @Override
    public SolicitudBO crearSolicitud(IntencionBO intencionBO) {

        SolicitudBO solicitud = new SolicitudBO();

        String tipoIntencion = intencionBO.getTipo();

        String sql = "SELECT "
                + " i2.numero "
                + "FROM "
                + " intencion i1 "
                + "  INNER JOIN intencion i2 "
                + "  ON i2.tipo != i1.tipo AND "
                + "   i2.estado = 'ABIERTA' AND "
                + "   i2.categoria = i1.categoria AND "
                + "   i2.producto = i1.producto AND "
                + "   i2.cantidad > i1.cantidad * .7 AND "
                + "   i2.cantidad < i1.cantidad * 1.3 AND "
                + "   i2.valor > i1.valor * .7 AND "
                + "   i2.valor < i1.valor * 1.3 "
                + "WHERE "
                + " i1.numero = ?1 "
                + "ORDER BY "
                + " i2.id ASC, i2.fecha_max_espera DESC, i2.valor "
                + (String) ((intencionBO.getTipo().equals(Intencion.T_COMPRA)) ? "DESC" : "ASC")
                + " LIMIT 0,1;";


        Query query = em.createNativeQuery(sql);
        query.setParameter(0, intencionBO.getId());
        List<Object> ret = query.getResultList();
        IntencionBO intencionMatch = null;
        if (ret != null && !ret.isEmpty()) {
            intencionMatch = obtenerIntencion((String) ret.get(0));
        }


        if (intencionMatch != null) {//¿hay una intencion con la que hay match?
            String numero = "SOL" + System.currentTimeMillis();
            solicitud.setNumero(numero);
            if (tipoIntencion != null && tipoIntencion.equals(Intencion.T_COMPRA)) {//¿Es una intencion de compra?
                solicitud.setIntencion_compra(intencionBO);
                solicitud.setIntencion_venta(intencionMatch);
                solicitud.setNumero_intencion_compra(intencionBO.getNumero());
                solicitud.setNumero_intencion_venta(intencionMatch.getNumero());

            } else if (tipoIntencion != null && tipoIntencion.equals(Intencion.T_VENTA)) {//¿Es una intencion de venta?
                solicitud.setIntencion_compra(intencionMatch);
                solicitud.setIntencion_venta(intencionBO);
                solicitud.setNumero_intencion_compra(intencionMatch.getNumero());
                solicitud.setNumero_intencion_venta(intencionBO.getNumero());

            }
            
            Solicitud solPersist = new Solicitud(solicitud);
            em.persist(solPersist);
        }
        return solicitud;
    }

    /**
     * Permite obtener un listado de intenciones a partir del nit y del tipo si
     * son de compra o de venta
     *
     * @param nit del interesado
     * @param tipo de la intencion compra o venta
     * @param estado de la intencion: abierta, vencida, exitosa, bloqueada
     * @return
     */
    @Override
    public List<IntencionBO> obtenerIntenciones(String nit, String tipo, String estado) {
        List<IntencionBO> auxIntencionBOs = new ArrayList<IntencionBO>();

        Query query = em.createNamedQuery("getListIntencionesByType");
        query.setParameter("nit", nit);
        query.setParameter("tipo", tipo.toUpperCase());
        query.setParameter("estado", estado.toUpperCase());

        List<Intencion> intenciones;
        intenciones = query.getResultList();

        if (intenciones != null && !intenciones.isEmpty()) {
            for (Intencion intencion : intenciones) {
                IntencionBO intencionBO = intencion.toBo();
                auxIntencionBOs.add(intencionBO);
            }
        }
        return auxIntencionBOs;
    }

    /**
     * Busca la solicitud relacionada a una intencion
     *
     * @param intencionBO
     * @return
     */
    @Override
    public SolicitudBO obtenerSolicitudPorIntencion(IntencionBO intencionBO) {
        String strQuery = "SELECT sol FROM Solicitud sol ";

        if (intencionBO.getTipo() != null && intencionBO.getTipo().toUpperCase().equals(Intencion.T_COMPRA)) {
            strQuery += " WHERE  sol.numero_intencion_compra = :numIntencion";
        } else if (intencionBO.getTipo() != null && intencionBO.getTipo().toUpperCase().equals(Intencion.T_VENTA)) {
            strQuery += " WHERE  sol.numero_intencion_venta = :numIntencion";
        }

        Query query = em.createQuery(strQuery);
        query.setParameter("numIntencion", intencionBO.getNumero());
        Solicitud solicitud = (Solicitud) query.getSingleResult();

        return new SolicitudBO(solicitud);//validar
    }

    /**
     * Permite a un fabricante o comercio confirmar una solicitudBO debe cambiar
     * el estado a la intencion!
     *
     * @param solicitudBO
     * @return
     */
    @Override
    public String confirmarSolicitud(SolicitudBO solicitudBO) {
        Query queryIntenc = em.createNamedQuery("getIntencionByNumero");
        Query querySolic = em.createNamedQuery("getSolicitudByNumero");
        querySolic.setParameter("numero", solicitudBO.getNumero());
        Solicitud solicitudActualizar = (Solicitud) querySolic.getSingleResult();
        
        if (solicitudActualizar != null) {
            if (solicitudBO.getTipo() != null && solicitudBO.getTipo().toUpperCase().equals(SolicitudBO.T_COMPRA)) {//Confirma Comercio
                queryIntenc.setParameter("numero", solicitudBO.getNumero_intencion_compra());
                solicitudActualizar.setConfirmacion_comercio(solicitudBO.getConfirmacion_comercio());
            } else if (solicitudBO.getTipo() != null && solicitudBO.getTipo().toUpperCase().equals(SolicitudBO.T_VENTA)) {//Confirma Fabricante
                queryIntenc.setParameter("numero", solicitudBO.getNumero_intencion_venta());
                solicitudActualizar.setConfirmacion_fabricante(solicitudBO.getConfirmacion_fabricante());
            }
        }
        
        //consulto la intencion
        Intencion intencion = (Intencion) queryIntenc.getSingleResult();
        //actualizo la intencion
        if (intencion != null) {
            intencion.setEstado(Intencion.E_EXITOSA);
            em.merge(intencion);
            //actualiza la solicitud
            em.merge(solicitudActualizar);
            return "succesfull updated";
        }

        return "fail";

    }

    /**
     * Permite actualizar el estado de una intencion
     *
     * @param id
     * @param estado
     * @return
     */
    @Override
    public String actualizarEstadoIntencion(String id, String estado) {

        Intencion intencion = new Intencion();
        int identificador = Integer.parseInt(id);
        intencion.setId(identificador);
        Query query =  em.createNamedQuery("getIntencionById");
        query.setParameter("id", identificador);
        
        if (query.getSingleResult() != null) {
            intencion = (Intencion) query.getSingleResult();
            intencion.setEstado(estado.toUpperCase());
            em.merge(intencion);
            return "succesfull updated";
        } else {
            return "fail";
        }
    }

    /**
     * Se cambia el estado de la intención y se habilita para búsqueda si la
     * fecha máxima es inferior a la actual
     *
     * @param solicitudBO
     * @return
     */
    @Override
    public String rechazarSolicitud(SolicitudBO solicitudBO) {

        Query query = em.createNamedQuery("getIntencionByNumero");

        if (solicitudBO.getNumero_intencion_compra() != null) {//¿el numero de la intencion de compra es diferente de null?
            query.setParameter("numero", solicitudBO.getNumero_intencion_compra());
        } else if (solicitudBO.getNumero_intencion_venta() != null) {//¿el numero de la intencion de venta es diferente de null?
            query.setParameter("numero", solicitudBO.getNumero_intencion_venta());
        }
        
        //actualizo la intencion
        if (query.getSingleResult() != null) {
            Intencion intencion = (Intencion) query.getSingleResult();
            long fechaMaxima = intencion.getFecha_max_espera().getTime();
            long fechaActual = new Date().getTime();

            if (fechaMaxima > fechaActual) {
                intencion.setEstado(Intencion.E_ABIERTA);//permito que este disponible para realizar match
            } else {
                intencion.setEstado(Intencion.E_VENCIDA);//no queda disponible para realizar match
            }
            em.merge(intencion);
            return "succesfull updated";
        }

        return "fail";

    }

    @Override
    public IntencionBO obtenerIntencion(String numero) {
        IntencionBO intencionBo = new IntencionBO();
        Query query = em.createNamedQuery("getIntencionByNumero");
        query.setParameter("numero", numero);
        Intencion intencion;
        if (query.getSingleResult() != null) {
            intencion = (Intencion) query.getSingleResult();
            intencionBo = intencion.toBo();
        }
        return intencionBo;

    }

    @Override
    public SolicitudBO obtenerSolicitud(String numero) {
        SolicitudBO solicitudBO = new SolicitudBO();
        Query query = em.createNamedQuery("getSolicitudByNumero");
        query.setParameter("numero", numero);

        Solicitud solicitud;
        if (query.getSingleResult() != null) {
            solicitud = (Solicitud) query.getSingleResult();
            solicitudBO = solicitud.toBo();
        }

        return solicitudBO;
    }

/*    public IntencionBO matchIntencion(IntencionBO intencion) {
        String sql = "SELECT "
                + " i2.id "
                + "FROM "
                + " intencion i1 "
                + "  INNER JOIN intencion i2 "
                + "  ON i2.tipo != i1.tipo AND "
                + "   i2.estado = 'ABIERTA' AND "
                + "   i2.categoria = i1.categoria AND "
                + "   i2.producto = i1.producto AND "
                + "   i2.cantidad > i1.cantidad * .7 AND "
                + "   i2.cantidad < i1.cantidad * 1.3 AND "
                + "   i2.valor > i1.valor * .7 AND "
                + "   i2.valor < i1.valor * 1.3 "
                + "WHERE "
                + " i1.id = ?1 "
                + "ORDER BY "
                + " i2.id ASC, i2.fecha_max_espera DESC, i2.valor "
                + (String) ((intencion.getTipo().equals(Intencion.T_COMPRA)) ? "DESC" : "ASC")
                + " LIMIT 0,1;";
        Query query = em.createNativeQuery(sql);
        query.setParameter(1, intencion.getId());
        List ret = query.getResultList();
        if (!ret.isEmpty()) {
            return (IntencionBO) obtenerIntencion((Integer) ret.get(0));
        } else {
            return null;
        }
    }*/
}
